/*
 * @Author: zi.yang
 * @Date: 2022-02-07 15:51:45
 * @LastEditors: zi.yang
 * @LastEditTime: 2022-02-07 22:31:45
 * @Description: 转换成 postman 格式
 * @FilePath: \api-generator\app\utils\toPostman.js
 */
'use strict';
const dayjs = require('dayjs');
const Encryption = require('./encryption');
/**
 * 生成描述
 * @param { Boolean } required 是否必填
 * @param { String } type 参数类型
 * @param { String } description 描述
 * @return { String } 描述文本
 */
function generatorDesc(required, type, description) {
  return `是否必填：${required ? '是' : '否'} - 参数类型：${type} - 描述：${description}`;
}

/**
 * 格式参数对象
 * @param {*} parameter 参数对象
 * @return { Object } 参数对象
 */
function formatParameter(parameter) {
  const { name: key, description, required, type, in: methodIn, 'x-example': example } = parameter;
  return { key, description, required, type, methodIn, example };
}

/**
 * 格式为 Get 请求查询参数
 * @param { Array } parameters 查询参数列表
 * @return { Array } 查询参数对象
 */
function formatGetParameters(parameters) {
  const query = [];
  parameters.forEach(parameter => {
    const { key, description, required, type, methodIn, example } = formatParameter(parameter);
    const isMap = methodIn === 'body' && key === 'map' && description === 'map';
    const isPath = methodIn === 'path';
    if (isMap || isPath) return;
    const desc = generatorDesc(required, type, description);
    query.push({ key, value: example || null, description: desc });
  });
  return query;
}

/**
 * 格式为 Post 请求查询参数
 * @param { Array } parameters 查询参数列表
 * @return { Array } 查询参数对象
 */
function formatPostParameters(parameters) {
  const rawContent = {};
  parameters.forEach(parameter => {
    const { key, description, methodIn } = formatParameter(parameter);
    const isMap = methodIn === 'body' && key === 'map' && description === 'map';
    const isPath = methodIn === 'path';
    if (isMap || isPath) return;
    Object.assign(rawContent, { [key]: '' });
  });
  return {
    body: {
      mode: 'raw',
      raw: JSON.stringify(rawContent),
      options: { raw: { language: 'json' } },
    },
  };
}

/**
 * 添加请求参数
 * @param { String } method 请求方法：GET|POST|PUT
 * @param { String } parameters 参数列表
 * @return { Object } postman 参数对象
 */
function addArgument(method, parameters) {
  let requestArgument = {};
  if (!parameters) return requestArgument;
  if (method === 'get') {
    const query = formatGetParameters(parameters);
    requestArgument = { query };
  } else {
    requestArgument = formatPostParameters(parameters);
  }
  return requestArgument;
}

/**
 * 请求描述文档
 * @param { Object } paramObj 描述文档信息
 * @return { String } 文档信息
 */
function requestDescriptionDoc({ summary, parameters, tags }) {
  let doc = `# ${tags.join('、')}\n\n`;
  doc += `## ${summary}\n\n`;
  if (!parameters) return doc;
  doc += '```javascript\n\n';
  doc += JSON.stringify({ ...parameters });
  doc += '\n\n```';
  return doc;
}

module.exports = swaggerContent => {
  const postmanRequestList = [];
  const name = 'postman-' + dayjs().format('YYYYMMDDHHmmss');
  const basePostman = {
    info: {
      _postman_id: Encryption.$md5(String(Math.random())),
      name,
      description: '',
      schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json',
    },
  };
  const { paths } = swaggerContent;
  Object.keys(paths).forEach(item => {
    const method = Object.keys(paths[item])[0];
    if (!method) return;
    const { summary, parameters, tags } = paths[item][method];
    const argument = addArgument(method, parameters);
    const description = requestDescriptionDoc({ summary, parameters, tags });
    const path = item.split('/').filter(item => item !== '');
    // 基本请求-模型
    const request = {
      name: summary,
      tags: tags[0],
      request: {
        method,
        header: [],
        url: {
          raw: `{{baseUrl}}${item}`,
          host: [
            '{{baseUrl}}',
          ],
          path,
          ...argument,
        },
        ...argument,
        description,
      },
      response: [],
    };
    if (method === 'get') {
      delete request.request.query;
    } else {
      delete request.request.url.body;
    }
    postmanRequestList.push(request);
  });
  Object.assign(basePostman, { item: postmanRequestList });
  return basePostman;
};
